/*
 * Copyright 2014 MovingBlocks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cola.machine.game.myblocks.logic.behavior.asset;

//import org.terasology.module.Module;

/**
 * Loader for behavior assets. Can also save assets into json format.
 * <p/>
 * If there are both, Nodes and Renderables tree, both are loaded/saved. To ensure, the nodes get associated to
 * the correct renderable, additional ids are introduced (only in the json file).
 * <p/>
 *
 * @author synopia
 */
public class BehaviorTreeLoader {
//        implements AssetLoader<BehaviorTreeData> {
//    private static final Logger logger = LoggerFactory.getLogger(BehaviorTreeLoader.class);
//    private BehaviorTreeGson treeGson = new BehaviorTreeGson();
//
//    public void save(OutputStream stream, BehaviorTreeData data) throws IOException {
//        try (JsonWriter write = new JsonWriter(new OutputStreamWriter(stream, Charsets.UTF_8))) {
//            write.setIndent("  ");
//            write.beginObject().name("model");
//            treeGson.saveTree(write, data.getRoot());
//            write.endObject();
//        }
//    }
//
//    @Override
//    public BehaviorTreeData load(Module module, InputStream stream, List<URL> urls, List<URL> deltas) throws IOException {
//        BehaviorTreeData data = new BehaviorTreeData();
//        try (JsonReader reader = new JsonReader(new InputStreamReader(stream, Charsets.UTF_8))) {
//            reader.setLenient(true);
//            reader.beginObject();
//            nextName(reader, "model");
//            data.setRoot(treeGson.loadTree(reader));
//            reader.endObject();
//        } catch (JsonSyntaxException e) {
//            logger.error("Cannot load tree! " + e.getMessage());
//            return null;
//        }
//        return data;
//    }
//
//    private String nextName(JsonReader in, String expectedName) throws IOException {
//        String name = in.nextName();
//        if (!expectedName.equals(name)) {
//            throw new RuntimeException(expectedName + " expected!");
//        }
//        return name;
//    }
//
//    private final class BehaviorTreeGson {
//        private int currentId;
//        private Map<Node, Integer> nodeIds = Maps.newHashMap();
//        private Map<Integer, Node> idNodes = Maps.newHashMap();
//
//        private Gson gsonNode;
//
//        private BehaviorTreeGson() {
//            gsonNode = new GsonBuilder()
//                    .setPrettyPrinting()
//                    .registerTypeAdapterFactory(new NodeTypeAdapterFactory())
//                    .registerTypeAdapter(BehaviorTree.class, new BehaviorTreeTypeAdapterFactory())
//                    .create();
//        }
//
//        public Node loadTree(JsonReader reader) {
//            resetIds();
//            return gsonNode.fromJson(reader, Node.class);
//        }
//
//        public void saveTree(JsonWriter writer, Node root) {
//            resetIds();
//            gsonNode.toJson(root, Node.class, writer);
//        }
//
//        public Node getNode(int id) {
//            return idNodes.get(id);
//        }
//
//        public int getId(Node node) {
//            return nodeIds.get(node);
//        }
//
//        private void resetIds() {
//            idNodes.clear();
//            nodeIds.clear();
//            currentId = 0;
//        }
//
//        private class NodeTypeAdapterFactory implements TypeAdapterFactory {
//            @Override
//            public <T> TypeAdapter<T> create(final Gson gson, TypeToken<T> type) {
//                final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
//                return new TypeAdapter<T>() {
//                    @Override
//                    public void write(JsonWriter out, T value) throws IOException {
//                        if (value instanceof Node) {
//                            out.beginObject();
//                            idNodes.put(currentId, (Node) value);
//                            nodeIds.put((Node) value, currentId);
//
//                            TypeAdapter<T> delegateAdapter = getDelegateAdapter(value.getClass());
//
//                            out.name("nodeType").value(CoreRegistry.get(NodesClassLibrary.class).getMetadata(((Node) value).getClass()).getUri().toString())
//                                    .name("nodeId").value(currentId);
//                            currentId++;
//                            out.name("node");
//                            delegateAdapter.write(out, value);
//                            out.endObject();
//                        } else {
//                            delegate.write(out, value);
//                        }
//                    }
//
//                    @Override
//                    public T read(JsonReader in) throws IOException {
//                        if (in.peek() == JsonToken.BEGIN_OBJECT) {
//                            in.beginObject();
//                            nextName(in, "nodeType");
//                            String nodeType = in.nextString();
//                            ClassMetadata<? extends Node, ?> classMetadata = CoreRegistry.get(NodesClassLibrary.class).resolve(nodeType);
//                            nextName(in, "nodeId");
//                            int id = in.nextInt();
//                            nextName(in, "node");
//                            if (classMetadata != null) {
//                                TypeAdapter<T> delegateAdapter = getDelegateAdapter(classMetadata.getType());
//                                Node result;
//                                if (classMetadata.getType() == LookupNode.class) {
//                                    result = classMetadata.newInstance();
//                                    in.beginObject();
//                                    nextName(in, "tree");
//                                    String uri = in.nextString();
//                                    ((LookupNode) result).tree = (BehaviorTree) Assets.resolve(AssetType.BEHAVIOR, uri);
//                                    in.endObject();
//                                } else {
//                                    result = (Node) delegateAdapter.read(in);
//                                }
//                                idNodes.put(id, result);
//                                nodeIds.put(result, id);
//                                in.endObject();
//                                return (T) result;
//                            } else {
//                                throw new NotSerializableException(nodeType);
//                            }
//                        } else {
//                            return delegate.read(in);
//                        }
//                    }
//
//                    private TypeAdapter<T> getDelegateAdapter(Class cls) {
//                        return (TypeAdapter<T>) gson.getDelegateAdapter(NodeTypeAdapterFactory.this, TypeToken.get(cls));
//                    }
//                };
//            }
//
//        }
//
//        private class BehaviorTreeTypeAdapterFactory extends TypeAdapter<BehaviorTree> {
//            @Override
//            public void write(JsonWriter out, BehaviorTree value) throws IOException {
//                if (value == null) {
//                    out.value("");
//                } else {
//                    out.value(value.getURI().toSimpleString());
//                }
//            }
//
//            @Override
//            public BehaviorTree read(JsonReader in) throws IOException {
//                String uri = in.nextString();
//                if (uri != null && uri.length() > 0) {
//                    return (BehaviorTree) Assets.resolve(AssetType.BEHAVIOR, in.nextString());
//                } else {
//                    return null;
//                }
//            }
//        }
//    }
}
